home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Commodities / ToBack&Front / toBack&Front.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  27KB  |  730 lines

  1. /*
  2.  *  toBack&Front.c
  3.  *
  4.  *  Commodity
  5.  *
  6.  *  Author: Stefan Sticht
  7.  *
  8.  *  Copyright: source is public domain, no copyright
  9.  *
  10.  *  Version history:
  11.  *
  12.  *  V1.00   initial release
  13.  *  V1.01   some minor changes
  14.  *  V1.02   changed myparseix for commodities.library 37.27
  15.  *          uses now utility.library's Stricmp()
  16.  *  V1.03   added some LockIBase()
  17.  *  V1.04   recompiled with changed (for 68040 compatiblity) cback.o
  18.  *          removed error when started from WB: taskpri wasn't set to 21 (thanks to Uwe Röhm)
  19.  *          TT_BACK_REMOVED never got parsed (nobody noticed?)
  20.  *  V1.05   removed bug that caused an Intuition lock up under certain circumstances;
  21.  *          some other small changes
  22.  *  V1.06   removed error where I called UnlockIBase(0l) instead of UnlockIBase(lock)
  23.  *  V1.07   cosmetic changes
  24.  *  V1.08   Sat 12-Oct-91 Stefan Sticht backorfront changed; another try to prevent lock ups
  25.  *  V1.09   Sat 12-Oct-91 Stefan Sticht changed startup to make program smaller,
  26.  *                                      changed argument parsing,
  27.  *                                      changed default action for toback,
  28.  *                                      added (back|front)_leftbuttonup
  29.  */
  30.  
  31. #define VERSION "V1.09"
  32.  
  33. /********************************************************************
  34.  *                             interfacing                          *
  35.  ********************************************************************/
  36.  
  37. /*
  38.  *  include files
  39.  */
  40.  
  41. #include <stdarg.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <devices/inputevent.h>
  45. #include <intuition/intuitionbase.h>
  46. #include <libraries/commodities.h>
  47. #include <workbench/icon.h>
  48. #include <workbench/startup.h>
  49.  
  50. #include <clib/alib_protos.h>
  51. #include <clib/commodities_protos.h>
  52. #include <clib/dos_protos.h>
  53. #include <clib/exec_protos.h>
  54. #include <clib/icon_protos.h>
  55. #include <clib/intuition_protos.h>
  56. #include <clib/layers_protos.h>
  57. #include <pragmas/commodities_pragmas.h>
  58. #include <pragmas/dos_pragmas.h>
  59. #include <pragmas/exec_pragmas.h>
  60. #include <pragmas/icon_pragmas.h>
  61. #include <pragmas/intuition_pragmas.h>
  62. #include <pragmas/layers_pragmas.h>
  63.  
  64. #ifdef DEBUG
  65. #define printf KPrintF
  66. #include <clib/dlib_protos.h>
  67. #endif
  68.  
  69. /*
  70.  *  prototypes
  71.  */
  72. struct Library *myopenlibrary(char *name, unsigned long version);
  73. void backorfront(unsigned short mode);
  74. void processmessages(void);
  75.  
  76. /* located in myparseix.c */
  77. long myparseix(char *description, IX *ix);
  78.  
  79. /*
  80.  *  global data
  81.  *
  82.  *  libraries opened by startup code; basepointers needed by function pragmas
  83.  */
  84. extern struct Library *DOSBase;
  85. extern struct Library *SysBase;
  86. extern struct WBStartup *WBenchMsg;
  87. /*
  88.  *  Disable SAS/C CTRL/C handling
  89.  */
  90. void chkabort(void) {}
  91.  
  92. /********************************************************************
  93.  *                             global data                          *
  94.  ********************************************************************/
  95.  
  96. /*
  97.  *  definition of messages
  98.  */
  99. #if defined(GERMAN)
  100. /*
  101.  *  Wenn jemand bessere Übersetzungsvorschläge hat, soll er mir die bitte mitteilen!
  102.  *  (This is german. If you don't understand, doesn't matter (belongs to the german version)
  103.  */
  104. #define COM_DESCR               "Fenster o. Schirm nach hinten o. vorne"
  105. #define COM_NAME                "toBack&Front"
  106. #define MSG_ERROR_IX            "Die Beschreibung für %s ist fehlerhaft!"
  107. #define MSG_ERROR_LIBRARY       "Die %s (V%ld+) kann nicht geöffnet werden!"
  108. #define RESUME_GADGETS          "Weiter"
  109. #define RETRY_GADGETS           "Wiederholen|Abbrechen"
  110.  
  111. #define OPT_BACK_ACTION         "BACK_AKTION"
  112. #define OPT_BACK_CLICKS         "BACK_CLICKS"
  113. #define OPT_BACK_REMOVE         "BACK_REMOVE"
  114. #define OPT_BACK_LEFTBUTTONUP   "BACK_LEFTBUTTONUP"
  115. #define OPT_FRONT_ACTION        "FRONT_AKTION"
  116. #define OPT_FRONT_CLICKS        "FRONT_CLICKS"
  117. #define OPT_FRONT_REMOVE        "FRONT_REMOVE"
  118. #define OPT_FRONT_LEFTBUTTONUP  "FRONT_LEFTBUTTONUP"
  119.  
  120. #define BY                      "von"
  121.  
  122. #else
  123.  
  124. #define COM_DESCR               "Window or screen to back or front"
  125. #define COM_NAME                "toBack&Front"
  126. #define MSG_ERROR_IX            "Error in description for %s!"
  127. #define MSG_ERROR_LIBRARY       "%s (V%ld+) can't be opened!"
  128. #define RESUME_GADGETS          "Resume"
  129. #define RETRY_GADGETS           "Retry|Cancel"
  130.  
  131. #define OPT_BACK_ACTION         "BACK_ACTION"
  132. #define OPT_BACK_CLICKS         "BACK_CLICKS"
  133. #define OPT_BACK_LEFTBUTTONUP   "BACK_LEFTBUTTONUP"
  134. #define OPT_BACK_REMOVE         "BACK_REMOVE"
  135. #define OPT_FRONT_ACTION        "FRONT_ACTION"
  136. #define OPT_FRONT_CLICKS        "FRONT_CLICKS"
  137. #define OPT_FRONT_REMOVE        "FRONT_REMOVE"
  138. #define OPT_FRONT_LEFTBUTTONUP  "FRONT_LEFTBUTTONUP"
  139.  
  140. #define BY                      "by"
  141.  
  142. #endif
  143.  
  144. #define COM_TITLE               COM_NAME " " VERSION
  145. #define OPT_CX_PRIORITY         "CX_PRIORITY"
  146.  
  147. #define DEF_BACK_ACTION         "rawmouse leftbutton rbutton rbuttoncode"
  148. #define DEF_BACK_CLICKS         1
  149. #define DEF_BACK_REMOVE         FALSE
  150. #define DEF_BACK_LEFTBUTTONUP   FALSE
  151. #define DEF_FRONT_ACTION        "rawmouse leftbutton lbuttoncode"
  152. #define DEF_FRONT_CLICKS        2
  153. #define DEF_FRONT_REMOVE        FALSE
  154. #define DEF_FRONT_LEFTBUTTONUP  FALSE
  155.  
  156. #define WARN                    5
  157. #define ERROR                   10
  158. #define FAIL                    20
  159.  
  160. #define FRONT                   1
  161. #define BACK                    2
  162.  
  163. /*
  164.  *  library base pointers
  165.  */
  166. struct IntuitionBase    *IntuitionBase;
  167. struct Library          *CxBase;
  168. struct Library          *IconBase;
  169. struct Library          *LayersBase;
  170.  
  171. /*
  172.  *  message ports
  173.  */
  174. struct MsgPort *cxport;
  175. unsigned long cxsigflag;
  176.  
  177. /*
  178.  *  programtitle and version for Version command
  179.  */
  180. char version[] ="\0$VER: " COM_TITLE " " BY " Stefan Sticht";
  181. #define TITLE_OFFSET 7l
  182.  
  183. /*
  184.  *  command line arguments for ReadArgs()
  185.  */
  186. #define TEMPLATE OPT_CX_PRIORITY "/K/N,"\
  187.                  OPT_BACK_ACTION "/K," OPT_BACK_CLICKS "/K/N," OPT_BACK_REMOVE "/S,"\
  188.                  OPT_BACK_LEFTBUTTONUP "/S,"\
  189.                  OPT_FRONT_ACTION "/K," OPT_FRONT_CLICKS "/K/N," OPT_FRONT_REMOVE "/S,"\
  190.                  OPT_FRONT_LEFTBUTTONUP "/S"
  191.  
  192. #define OPTN_CX_PRIORITY        0
  193. #define OPTN_BACK_ACTION        1
  194. #define OPTN_BACK_CLICKS        2
  195. #define OPTN_BACK_REMOVE        3
  196. #define OPTN_BACK_LEFTBUTTONUP  4
  197. #define OPTN_FRONT_ACTION       5
  198. #define OPTN_FRONT_CLICKS       6
  199. #define OPTN_FRONT_REMOVE       7
  200. #define OPTN_FRONT_LEFTBUTTONUP 8
  201. #define OPTN_COUNT              9
  202. long options[OPTN_COUNT];
  203.  
  204. /*
  205.  *  number of clicks required
  206.  */
  207. unsigned char requiredbackclicks    = DEF_BACK_CLICKS;
  208. unsigned char requiredfrontclicks   = DEF_FRONT_CLICKS;
  209. unsigned char back_leftbuttonup     = DEF_BACK_LEFTBUTTONUP;
  210. unsigned char front_leftbuttonup    = DEF_FRONT_LEFTBUTTONUP;
  211.  
  212. /*
  213.  *  our broker
  214.  */
  215. CxObj *broker;
  216. struct NewBroker newbroker = {
  217.     NB_VERSION,                         /* BYTE nb_Version               */
  218.     COM_NAME,                           /* BYTE *nb_Name                 */
  219.     &version[TITLE_OFFSET],             /* BYTE *nb_Title                */
  220.     COM_DESCR,                          /* BYTE *nb_Descr                */
  221.     NBU_NOTIFY | NBU_UNIQUE,            /* SHORT nb_Unique               */
  222.     0,                                  /* SHORT nb_Flags                */
  223.     0,                                  /* BYTE nb_Pri                   */
  224.     NULL,                               /* struct MsgPort nb_Port        */
  225.     0                                   /* WORD nb_ReservedChannel       */
  226.     };
  227.  
  228. IX backix = {
  229.     IX_VERSION,                 /* UBYTE ix_version     */
  230.     0,                          /* UBYTE ix_Class       */
  231.     0,                          /* UWORD ix_Code        */
  232.     0,                          /* UWORD ix_CodeMask    */
  233.     0,                          /* UWORD ix_Qualifier   */
  234.     0,                          /* UWORD ix_QualMask    */
  235.     0                           /* UWORD ix_QualSame    */
  236.     };
  237.  
  238. IX frontix = {
  239.     IX_VERSION,                 /* UBYTE ix_version     */
  240.     0,                          /* UBYTE ix_Class       */
  241.     0,                          /* UWORD ix_Code        */
  242.     0,                          /* UWORD ix_CodeMask    */
  243.     0,                          /* UWORD ix_Qualifier   */
  244.     0,                          /* UWORD ix_QualMask    */
  245.     0                           /* UWORD ix_QualSame    */
  246.     };
  247.  
  248. struct InputEvent ievent = {
  249.     NULL,                               /* struct  InputEvent *ie_NextEvent */
  250.     IECLASS_RAWMOUSE,                   /* UBYTE   ie_Class;                */
  251.     0,                                  /* UBYTE   ie_SubClass;             */
  252.     IECODE_LBUTTON | IECODE_UP_PREFIX,  /* UWORD   ie_Code;                 */
  253.     IEQUALIFIER_RELATIVEMOUSE,          /* UWORD   ie_Qualifier;            */
  254.     {0, 0},
  255.     {0, 0},
  256.     };
  257.  
  258. /********************************************************************
  259.  *                             functions                            *
  260.  ********************************************************************/
  261.  
  262. /*
  263.  *  request(): a glue routine to EasyRequest as simple as printf plus
  264.  *             titlestring, gadgettexts
  265.  *
  266.  *  Input: char *title:         pointer to the title of the requester
  267.  *         char *gadgets:       pointer to gadgettext
  268.  *         char *text:          text displayed in requester
  269.  *
  270.  *  Result: same as EasyrequestArgs()
  271.  *
  272.  * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!!
  273.  */
  274. long request(char *title, char *gadgets, char *text, ...)
  275. {
  276.     /*
  277.      *  structure textreq only needed in this function, so hide it here
  278.      *  must be static, in order to be initialized only once
  279.      */
  280.     static struct EasyStruct textreq = {
  281.         sizeof (struct EasyStruct), /* ULONG es_StructSize      */
  282.         0l,                         /* ULONG es_Flags           */
  283.         NULL,                       /* UBYTE *es_Title          */
  284.         NULL,                       /* UBYTE *es_TextFormat     */
  285.         NULL,                       /* UBYTE *es_GadgetFormat   */
  286.         };
  287.     va_list ap;
  288.     long rc;
  289.  
  290.     /*
  291.      *  get start of variable arguments
  292.      */
  293.     va_start(ap, text);
  294.  
  295.     /*
  296.      *  update textreq
  297.      */
  298.     textreq.es_Title = (UBYTE *)title;
  299.     textreq.es_TextFormat = (UBYTE *)text;
  300.     textreq.es_GadgetFormat = (UBYTE *)gadgets;
  301.  
  302.     /*
  303.      *  win may be NULL
  304.      */
  305.     rc = EasyRequestArgs(NULL, &textreq, NULL, ap);
  306.  
  307.     va_end(ap);
  308.  
  309.     return(rc);
  310. }
  311.  
  312. /*
  313.  *  myopenlibrary(): same as OpenLibrary(), but opens a retry-requester
  314.  *                   if OpenLibrary() fails, to give the user a chance to
  315.  *                   copy the library to libs: and retry
  316.  *                   requires request(), see above
  317.  */
  318. struct Library *myopenlibrary(char *name, unsigned long version)
  319. {
  320.     static char errortext[] = MSG_ERROR_LIBRARY;
  321.     struct Library *libptr;
  322.     long ok = TRUE;
  323.  
  324.     do {
  325.         if (!(libptr = OpenLibrary((UBYTE *)name, version))) {
  326.             if (IntuitionBase) ok = request(COM_NAME, RETRY_GADGETS, errortext, name, version);
  327.             else ok = FALSE;
  328.             }
  329.         } while (!libptr && ok);
  330.  
  331.     return(libptr);
  332. }
  333.  
  334. void _main(char *line)
  335. {
  336.     CxObj *backfilter = NULL;
  337.     CxObj *frontfilter = NULL;
  338.     CxObj *obj;
  339.     long error;
  340.     struct Message *msg;
  341.     struct Task *mytask;
  342.     unsigned long rc = 0;
  343.     unsigned char backremove = DEF_BACK_REMOVE;
  344.     unsigned char frontremove = DEF_FRONT_REMOVE;
  345.     char startpri;
  346.  
  347.     if (IntuitionBase = (struct IntuitionBase *)myopenlibrary("intuition.library", 37l)) {
  348.  
  349.         if (CxBase = myopenlibrary("commodities.library", 37l)) {
  350.  
  351.             if (!WBenchMsg) {
  352.                 /*
  353.                  *  started from Shell
  354.                  */
  355.                 struct RDArgs *args;
  356.                 /*
  357.                  *  change name of program
  358.                  */
  359.                 SetProgramName(COM_NAME);
  360.                 /*
  361.                  *  display banner
  362.                  */
  363.                 PutStr(&version[TITLE_OFFSET]); PutStr("\n");
  364.                 /*
  365.                  *  parse command line
  366.                  */
  367.                 if (args = ReadArgs((UBYTE *)TEMPLATE, options, NULL)) {
  368.  
  369.                     if (options[OPTN_CX_PRIORITY])  newbroker.nb_Pri = (BYTE)*((long *)options[OPTN_CX_PRIORITY]);
  370.                     if (options[OPTN_BACK_ACTION])  error = myparseix((char *)options[OPTN_BACK_ACTION], &backix);
  371.                     else error = myparseix(DEF_BACK_ACTION, &backix);
  372.                     if (error) {
  373.                         char *s = OPT_BACK_ACTION;
  374.                         VPrintf(MSG_ERROR_IX, (long *)&s);
  375.                         PutStr("\n");
  376.                         rc = ERROR;
  377.                         }
  378.                     if (options[OPTN_BACK_CLICKS])  requiredbackclicks = (unsigned char)*((long *)options[OPTN_BACK_CLICKS]);
  379.                     if (options[OPTN_BACK_REMOVE])  backremove = TRUE;
  380.                     if (options[OPTN_BACK_LEFTBUTTONUP] &&
  381.                         (backix.ix_Code & ~IECODE_LBUTTON) &&
  382.                         (backix.ix_Qualifier & IEQUALIFIER_LEFTBUTTON)) back_leftbuttonup = TRUE;
  383.                     if (options[OPTN_FRONT_ACTION]) error = myparseix((char *)options[OPTN_FRONT_ACTION], &frontix);
  384.                     else error = myparseix(DEF_FRONT_ACTION, &frontix);
  385.                     if (error) {
  386.                         char *s = OPT_FRONT_ACTION;
  387.                         VPrintf(MSG_ERROR_IX, (long *)&s);
  388.                         PutStr("\n");
  389.                         rc = ERROR;
  390.                         }
  391.                     if (options[OPTN_FRONT_CLICKS]) requiredfrontclicks = (unsigned char)*((long *)options[OPTN_FRONT_CLICKS]);
  392.                     if (options[OPTN_FRONT_REMOVE]) frontremove = TRUE;
  393.                     if (options[OPTN_FRONT_LEFTBUTTONUP] &&
  394.                         (frontix.ix_Code & ~IECODE_LBUTTON) &&
  395.                         (frontix.ix_Qualifier & IEQUALIFIER_LEFTBUTTON)) front_leftbuttonup = TRUE;
  396.                     /*
  397.                      *  we don't look anylonger at args, so we can release them
  398.                      */
  399.                     FreeArgs(args);
  400.                     }
  401.                 else {
  402.                     /*
  403.                      *  error parsing args
  404.                      */
  405.                     PrintFault(IoErr(), NULL);
  406.                     rc = WARN;
  407.                     }
  408.                 }
  409.  
  410.             else {
  411.                 BPTR olddir = -1l;
  412.                 char *tooltype;
  413.                 char **tooltypesarray;
  414.                 struct DiskObject *diskobj;
  415.                 struct Library *IconBase;
  416.                 struct WBArg *wbarg;
  417.  
  418.                 if (IconBase = myopenlibrary(ICONNAME, 37l)) {
  419.  
  420.                     if (wbarg = &(WBenchMsg->sm_ArgList)[WBenchMsg->sm_NumArgs - 1l]) {
  421.  
  422.                         if (wbarg->wa_Name) {
  423.  
  424.                             if (wbarg->wa_Lock) olddir = CurrentDir(wbarg->wa_Lock);
  425.  
  426.                             if (diskobj = GetDiskObject(wbarg->wa_Name)) {
  427.  
  428.                                 tooltypesarray = diskobj->do_ToolTypes;
  429.  
  430.                                 if (tooltype = FindToolType(tooltypesarray, OPT_CX_PRIORITY)) newbroker.nb_Pri = (BYTE)atol(tooltype);
  431.                                 if (tooltype = FindToolType(tooltypesarray, OPT_BACK_ACTION)) error = myparseix(tooltype, &backix);
  432.                                 else error = myparseix(DEF_BACK_ACTION, &backix);
  433.                                 if (error) {
  434.                                     request(COM_NAME, RESUME_GADGETS, MSG_ERROR_IX, OPT_BACK_ACTION);
  435.                                     rc = ERROR;
  436.                                     }
  437.                                 if (tooltype = FindToolType(tooltypesarray, OPT_BACK_CLICKS)) requiredbackclicks = (unsigned char)atol(tooltype);
  438.                                 if (FindToolType(tooltypesarray, OPT_BACK_REMOVE)) backremove = TRUE;
  439.                                 if (FindToolType(tooltypesarray, OPT_BACK_LEFTBUTTONUP) &&
  440.                                     (backix.ix_Code & ~IECODE_LBUTTON) &&
  441.                                     (backix.ix_Qualifier & IEQUALIFIER_LEFTBUTTON)) back_leftbuttonup = TRUE;
  442.                                 if (tooltype = FindToolType(tooltypesarray, OPT_FRONT_ACTION)) error = myparseix(tooltype, &frontix);
  443.                                 else error = myparseix(DEF_FRONT_ACTION, &frontix);
  444.                                 if (error) {
  445.                                     request(COM_NAME, RESUME_GADGETS, MSG_ERROR_IX, OPT_FRONT_ACTION);
  446.                                     rc = ERROR;
  447.                                     }
  448.                                 if (tooltype = FindToolType(tooltypesarray, OPT_FRONT_CLICKS)) requiredfrontclicks = (unsigned char)atol(tooltype);
  449.                                 if (FindToolType(tooltypesarray, OPT_FRONT_REMOVE)) frontremove = TRUE;
  450.                                 if (FindToolType(tooltypesarray, OPT_FRONT_LEFTBUTTONUP) &&
  451.                                     (frontix.ix_Code & ~IECODE_LBUTTON) &&
  452.                                     (frontix.ix_Qualifier & IEQUALIFIER_LEFTBUTTON)) front_leftbuttonup = TRUE;
  453.  
  454.                                 FreeDiskObject(diskobj);
  455.  
  456.                                 } /* if diskobj */
  457.  
  458.                             if (olddir != -1l) CurrentDir(olddir);
  459.  
  460.                             } /* if wbarg->wa_Name */
  461.  
  462.                         } /* if wbarg */
  463.  
  464.                     CloseLibrary(IconBase);
  465.  
  466.                     } /* if IconBase */
  467.  
  468.                 } /* if WBenchMsg */
  469.  
  470.             if ((CheckSignal(SIGBREAKF_CTRL_C) == DOSFALSE) &&
  471.                 !rc && (LayersBase = myopenlibrary("layers.library", 37l))) {
  472.  
  473.                 if (frontix.ix_Class || backix.ix_Class) {
  474.                     /*
  475.                      *  create our message port
  476.                      */
  477.                     if (cxport = CreateMsgPort()) {
  478.  
  479.                         cxsigflag = 1l << cxport->mp_SigBit;
  480.                         newbroker.nb_Port = cxport;
  481.                         /*
  482.                          *  open broker
  483.                          */
  484.                         if (broker = CxBroker(&newbroker, NULL)) {
  485.  
  486.                             if (backix.ix_Class && (backfilter = CxFilter(NULL))) {
  487.                                 SetFilterIX(backfilter, &backix);
  488.                                 AttachCxObj(broker, backfilter);
  489.                                 if (obj = CxSender(cxport, BACK)) {
  490.                                     AttachCxObj(backfilter, obj);
  491.                                     if (backremove && (obj = CxTranslate(NULL))) AttachCxObj(backfilter, obj);
  492.                                     }
  493.                                 }
  494.  
  495.                             if (frontix.ix_Class && (frontfilter = CxFilter(NULL))) {
  496.                                 SetFilterIX(frontfilter, &frontix);
  497.                                 AttachCxObj(broker, frontfilter);
  498.                                 if (obj = CxSender(cxport, FRONT)) {
  499.                                     AttachCxObj(frontfilter, obj);
  500.                                     if (frontremove && (obj = CxTranslate(NULL))) AttachCxObj(frontfilter, obj);
  501.                                     }
  502.                                 }
  503.  
  504.                             if (!CxObjError(broker) &&
  505.                                 ((frontfilter && !CxObjError(frontfilter)) ||
  506.                                 (backfilter && !CxObjError(backfilter)))) {
  507.  
  508.                                 if (mytask = FindTask(NULL)) {
  509.                                     /*
  510.                                      *  change priority of our process
  511.                                      */
  512.                                     startpri = SetTaskPri(mytask, 21l);
  513.                                     /*
  514.                                      *  activate our commodity
  515.                                      */
  516.                                     ActivateCxObj(broker, 1l);
  517.                                     /*
  518.                                      *  now watch our port
  519.                                      */
  520.                                     processmessages();
  521.                                     /*
  522.                                      *  change to old priority
  523.                                      */
  524.                                     SetTaskPri(mytask, (long)startpri);
  525.                                     } /* if mytask */
  526.  
  527.                                 } /* if !CxObjError() */
  528.  
  529.                             DeleteCxObjAll(broker);
  530.  
  531.                             } /* if broker */
  532.  
  533.                         /*
  534.                          *  delete our message port after replying all pending messages
  535.                          */
  536.                         while (msg = GetMsg(cxport)) ReplyMsg(msg);
  537.                         DeleteMsgPort(cxport);
  538.                         } /* if cxport */
  539.  
  540.                     #ifdef DEBUG
  541.                     else printf("main(): CreateMsgPort() failed!\n");
  542.                     #endif
  543.  
  544.                     } /* if (frontaction || backaction) */
  545.  
  546.                 CloseLibrary(LayersBase);
  547.                 } /* if LayersBase */
  548.  
  549.             CloseLibrary(CxBase);
  550.             } /* if CxBase */
  551.  
  552.         CloseLibrary((struct Library *)IntuitionBase);
  553.         } /* if IntuitionBase */
  554.  
  555.     _exit(rc);
  556.  
  557. } /* main() */
  558.  
  559. void processmessages(void)
  560. {
  561.     static unsigned long lastfrontmicros = 0l;
  562.     static unsigned long lastfrontsecs = 0l;
  563.     static unsigned long lastbackmicros = 0l;
  564.     static unsigned long lastbacksecs = 0l;
  565.     static unsigned char frontclicks = 0;
  566.     static unsigned char backclicks = 0;
  567.     struct InputEvent *ie;
  568.     struct Message *msg;
  569.     unsigned long sigreceived;
  570.     unsigned long msgtype;
  571.     unsigned long msgid;
  572.     unsigned long micros;
  573.     unsigned long secs;
  574.     unsigned char quit = FALSE;
  575.  
  576.     if (requiredfrontclicks == 1) frontclicks = 1;
  577.     if (requiredbackclicks == 1) backclicks = 1;
  578.  
  579.     while (!quit) {
  580.  
  581.         sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag);
  582.  
  583.         #ifdef DEBUG
  584.         printf("processmessages(): signal received\n");
  585.         #endif
  586.  
  587.         if (sigreceived & cxsigflag) {
  588.  
  589.             while (msg = (struct Message *)GetMsg(cxport)) {
  590.  
  591.                 msgid = CxMsgID((CxMsg *)msg);
  592.                 msgtype = CxMsgType((CxMsg *)msg);
  593.  
  594.                 if ((msgtype == CXM_IEVENT) &&
  595.                     (ie = (struct InputEvent *)CxMsgData((CxMsg *)msg))) {
  596.                     /*
  597.                      *  copy the interesting data of the inputevent
  598.                      */
  599.                     secs = ie->ie_TimeStamp.tv_secs;
  600.                     micros = ie->ie_TimeStamp.tv_micro;
  601.                     }
  602.  
  603.                 ReplyMsg(msg);
  604.  
  605.                 switch (msgtype) {
  606.  
  607.                     case CXM_IEVENT:
  608.                         switch (msgid) {
  609.  
  610.                             case FRONT:
  611.                                 if (requiredfrontclicks > 1) {
  612.                                     if (DoubleClick(lastfrontsecs, lastfrontmicros, secs, micros))
  613.                                         frontclicks++;
  614.                                     else frontclicks = 1;
  615.  
  616.                                     lastfrontsecs = secs;
  617.                                     lastfrontmicros = micros;
  618.                                     }
  619.                                 if (frontclicks == requiredfrontclicks) {
  620.                                     backorfront(FRONT);
  621.                                     if (requiredfrontclicks > 1) frontclicks = 0;
  622.                                     }
  623.                                 break;
  624.  
  625.                             case BACK:
  626.                                 if (requiredbackclicks > 1) {
  627.                                     if (DoubleClick(lastbacksecs, lastbackmicros, secs, micros))
  628.                                         backclicks++;
  629.                                     else backclicks = 1;
  630.  
  631.                                     lastbacksecs = secs;
  632.                                     lastbackmicros = micros;
  633.                                     }
  634.                                 if (backclicks == requiredbackclicks) {
  635.                                     backorfront(BACK);
  636.                                     if (requiredbackclicks > 1) backclicks = 0;
  637.                                     }
  638.                                 break;
  639.  
  640.                             }
  641.  
  642.                     case CXM_COMMAND:
  643.                         switch (msgid) {
  644.  
  645.                             case CXCMD_UNIQUE:
  646.                             case CXCMD_KILL:
  647.                                 quit = TRUE;
  648.  
  649.                             case CXCMD_DISABLE:
  650.                                 ActivateCxObj(broker, 0l);
  651.                                 break;
  652.  
  653.                             case CXCMD_ENABLE:
  654.                                 ActivateCxObj(broker, 1l);
  655.                                 break;
  656.  
  657.                             }
  658.                         break;
  659.  
  660.                     } /* switch msgtype */
  661.  
  662.                 } /* while CxMsg */
  663.  
  664.             } /* if (sigreceived & cxsigflag) */
  665.  
  666.         if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE;
  667.  
  668.         } /* while !quit */
  669.  
  670.     ActivateCxObj(broker, 0l);
  671. }
  672.  
  673. void backorfront(unsigned short mode)
  674. {
  675.     struct Screen *scr;
  676.     struct Layer *layer;
  677.     struct Window *win;
  678.  
  679.     Forbid();
  680.  
  681.     /*
  682.      *  here we go: find screen
  683.      */
  684.     for (scr = IntuitionBase->FirstScreen;
  685.          scr && (scr->TopEdge > 0) && (scr->MouseY < 0);
  686.          scr = scr->NextScreen);
  687.  
  688.     if (scr) {
  689.  
  690.         if (layer = WhichLayer(&scr->LayerInfo, (long)scr->MouseX, (long)scr->MouseY)) {
  691.  
  692.             if ((layer != scr->BarLayer) &&
  693.                 (win = (struct Window *)layer->Window) &&
  694.                 !(win->Flags & BACKDROP)) {
  695.  
  696.                 if (win->NextWindow || win->WScreen->FirstWindow != win) {
  697.  
  698.                     if (mode == BACK) {
  699.                         WindowToBack(win);
  700.                         if (back_leftbuttonup && win->WLayer->LayerInfo->LockLayersCount) AddIEvents(&ievent);
  701.                         }
  702.                     else {
  703.                         WindowToFront(win);
  704.                         if (front_leftbuttonup && win->WLayer->LayerInfo->LockLayersCount) AddIEvents(&ievent);
  705.                         }
  706.                     }
  707.  
  708.                 } /* if win */
  709.  
  710.             else {
  711.                 /*
  712.                  *  screen to back/front
  713.                  */
  714.                 if (mode == BACK) {
  715.                     if (back_leftbuttonup && (layer == scr->BarLayer)) AddIEvents(&ievent);
  716.                     ScreenToBack(scr);
  717.                     }
  718.                 else if (scr != IntuitionBase->FirstScreen) {
  719.                     if (front_leftbuttonup && (layer == scr->BarLayer)) AddIEvents(&ievent);
  720.                     ScreenToFront(scr);
  721.                     }
  722.                 }
  723.  
  724.             } /* if layer */
  725.  
  726.         } /* if scr */
  727.  
  728.     Permit();
  729.  
  730. }